#ifndef CPU68K_H
#define CPU68K_H

#define CPU68K_AUTOVECTOR_BASE_EX   24

#define CPU68K_INT_ACK_AUTOVECTOR   -1

typedef u32     FASTCALL CPU68K_READ(const u32 adr);
typedef void    FASTCALL CPU68K_WRITE(const u32 adr, u32 data);

typedef u32     FASTCALL CPU68K_INT_CALLBACK(u32 level);
typedef void    FASTCALL CPU68K_RESET_CALLBACK(void);
/*
void M68K_GetContext(void);
void M68K_SetContext(void);

u32 M68K_GetCurrentCore(void);
void M68K_SetCurrentCore(u32 core);
*/

void M68K_Init(int type);
/*s32  M68K_Reset(void);

s32  M68K_Exec(s32 cycles);

void M68K_SetIRQ(u32 level);

u32  M68K_GetOdo(void);
void M68K_EndExec(void);

void M68K_SetFetch(u32 low_adr, u32 high_adr, u32 fetch_adr);

u32  M68K_GetDReg(u32 num);
u32  M68K_GetAReg(u32 num);
u32  M68K_GetSP(void);
u32  M68K_GetPC(void);
u32  M68K_GetSR(void);

void M68K_SetAReg(u32 num, u32 val);
void M68K_SetDReg(u32 num, u32 val);
void M68K_SetSP(u32 val);
void M68K_SetPC(u32 val);
void M68K_SetSR(u32 val);

u8  *M68K_Disassemble(u32 *PC);*/

#include "fame.h"
#include "c68k.h"

#ifdef CPU68K_USE_MUSASHI
	#include "m68k.h"
	#include "m68kcpu.h"
#endif

INLINE void M68K_Reset(int cpu68k_type)
{
  switch(cpu68k_type)
  {
    case 0:
      // C68K
      C68k_Reset(&C68K);
      break;
    case 1:
      // FAME
      m68k_reset();
      break;
    #ifdef CPU68K_USE_MUSASHI
    case 2:
      // MUSASHI
      m68k_pulse_reset();
      break;
    #endif
  }
}

INLINE s32 M68K_Exec(int cpu68k_type, s32 cycles)
{
  switch(cpu68k_type)
  {
    case 0:
      // C68K
      return C68k_Exec(&C68K, cycles);
    case 1:
      // FAME
      return m68k_emulate(cycles);
    #ifdef CPU68K_USE_MUSASHI
    case 2:
      // MUSASHI
      return m68k_execute(cycles);
    #endif
  }
}

INLINE void M68K_SetIRQ(int cpu68k_type, u32 level)
{
  switch(cpu68k_type)
  {
    case 0:
      // C68K
      C68k_Set_IRQ(&C68K, level);
      break;
    case 1:
      // FAME
      m68k_raise_irq(level, M68K_AUTOVECTORED_IRQ);
      break;
    #ifdef CPU68K_USE_MUSASHI
    case 2:
      // MUSASHI
      m68k_set_irq(level);
      break;
    #endif
  }
}

INLINE void M68K_LowerIRQ(int cpu68k_type, u32 level)
{
  switch(cpu68k_type)
  {
    case 0:
      // C68K
      C68k_Set_IRQ(&C68K, 0);
      break;
    case 1:
      // FAME
      m68k_lower_irq(level);
      break;
    #ifdef CPU68K_USE_MUSASHI
    case 2:
      // MUSASHI
      m68k_set_irq(0);
      break;
    #endif
  }
}

INLINE u32 M68K_GetOdo(int cpu68k_type)
{
	switch(cpu68k_type)
	{
		case 0:
			// C68K
			return C68k_Get_CycleDone(&C68K);
		case 1:
			// FAME
			return m68k_get_cycles_counter();

		#ifdef CPU68K_USE_MUSASHI
		case 2:
			return m68k_cycles_run();
		#endif
	}
}

INLINE void M68K_EndExec(/*int cpu68k_type*/)
{
/*	switch(cpu68k_type)
	{
		case 0:
			// C68K
			C68k_Release_Cycle(&C68K);
			return;
		case 1:
			// FAME
			m68k_release_timeslice();
			return;

#ifdef CPU68K_USE_MUSASHI
		case 2:
			m68k_end_timeslice();
			return;
#endif
}*/
}

/*
INLINE void M68K_SetFetch(u32 low_adr, u32 high_adr, u32 fetch_adr)
{
    // C68K
#ifdef CPU68K_USE_C68K
    C68k_Set_Fetch(&C68K, low_adr, high_adr, fetch_adr);
#endif
}
*/
/*
INLINE u32 M68K_GetDReg(u32 num)
{
#ifdef CPU68K_USE_MUSASHI
    return m68k_get_reg(NULL, M68K_REG_D0 + num);
#endif

#ifdef CPU68K_USE_C68K
    return C68k_Get_DReg(&C68K, num);
#endif

#ifdef CPU68K_USE_FAME
	return m68k_get_register(M68K_REG_D0 + num);
#endif

}

INLINE u32 M68K_GetAReg(u32 num)
{
#ifdef CPU68K_USE_MUSASHI
    return m68k_get_reg(NULL, M68K_REG_A0 + num);
#endif

#ifdef CPU68K_USE_C68K
    return C68k_Get_AReg(&C68K, num);
#endif

#ifdef CPU68K_USE_FAME
	return m68k_get_register(M68K_REG_A0 + num);
#endif
}

INLINE u32 M68K_GetSP(void)
{
    return M68K_GetAReg(7);
}

INLINE u32 M68K_GetPC(int cpu68k_type)
{
  switch(cpu68k_type)
  {
    case 0:
      // C68K
      return C68k_Get_PC(&C68K);
    case 1:
      // FAME
      return m68k_get_register(M68K_REG_PC);
    #ifdef CPU68K_USE_MUSASHI
    case 2:
      // MUSASHI
      return m68k_get_reg(NULL, M68K_REG_PC);
    #endif
  }
}

INLINE u32 M68K_GetSR(void)
{
#ifdef CPU68K_USE_MUSASHI
    return m68k_get_reg(NULL, M68K_REG_SR);
#endif

#ifdef CPU68K_USE_C68K
    return C68k_Get_SR(&C68K);
#endif

#ifdef CPU68K_USE_FAME
	return m68k_get_register(M68K_REG_SR);
#endif
}

INLINE u32 M68K_GetMSP(void)
{
#ifdef CPU68K_USE_MUSASHI
    return m68k_get_reg(NULL, M68K_REG_ISP);
#endif

#ifdef CPU68K_USE_C68K
    return C68k_Get_MSP(&C68K);
#endif

#ifdef CPU68K_USE_FAME
	return m68k_get_register(M68K_REG_A7);
#endif
}

INLINE u32 M68K_GetUSP(void)
{
#ifdef CPU68K_USE_MUSASHI
    return m68k_get_reg(NULL, M68K_REG_USP);
#endif

#ifdef CPU68K_USE_C68K
    return C68k_Get_USP(&C68K);
#endif

#ifdef CPU68K_USE_FAME
	return m68k_get_register(M68K_REG_ASP);
#endif
}

INLINE void M68K_SetDReg(u32 num, u32 val)
{
#ifdef CPU68K_USE_MUSASHI
    m68k_set_reg(M68K_REG_D0 + num, val);
#endif

#ifdef CPU68K_USE_C68K
    C68k_Set_DReg(&C68K, num, val);
#endif

#ifdef CPU68K_USE_FAME
	m68k_set_register(M68K_REG_D0 + num, val);
#endif
}

INLINE void M68K_SetAReg(u32 num, u32 val)
{
#ifdef CPU68K_USE_MUSASHI
    m68k_set_reg(M68K_REG_A0 + num, val);
#endif

#ifdef CPU68K_USE_C68K
    C68k_Set_AReg(&C68K, num, val);
#endif

#ifdef CPU68K_USE_FAME
	m68k_set_register(M68K_REG_A0 + num, val);
#endif
}

INLINE void M68K_SetSP(u32 val)
{
    M68K_SetAReg(7, val);
}

INLINE void M68K_SetPC(u32 val)
{
#ifdef CPU68K_USE_MUSASHI
    m68k_set_reg(M68K_REG_PC, val);
#endif

#ifdef CPU68K_USE_C68K
    C68k_Set_PC(&C68K, val);
#endif

#ifdef CPU68K_USE_FAME
	m68k_set_register(M68K_REG_PC, val);
#endif
}

INLINE void M68K_SetSR(u32 val)
{
#ifdef CPU68K_USE_MUSASHI
    m68k_set_reg(M68K_REG_SR, val);
#endif

#ifdef CPU68K_USE_C68K
    C68k_Set_SR(&C68K, val);
#endif

#ifdef CPU68K_USE_FAME
	m68k_set_register(M68K_REG_SR, val);
#endif
}

INLINE void M68K_SetMSP(u32 val)
{
#ifdef CPU68K_USE_MUSASHI
    m68k_set_reg(M68K_REG_ISP, val);
#endif

#ifdef CPU68K_USE_C68K
    C68k_Set_MSP(&C68K, val);
#endif

#ifdef CPU68K_USE_FAME
	m68k_set_register(M68K_REG_A7, val);
#endif
}

INLINE void M68K_SetUSP(u32 val)
{
#ifdef CPU68K_USE_MUSASHI
    m68k_set_reg(M68K_REG_USP, val);
#endif

#ifdef CPU68K_USE_C68K
    C68k_Set_USP(&C68K, val);
#endif

#ifdef CPU68K_USE_FAME
	m68k_set_register(M68K_REG_ASP, val);
#endif
}
*/

#endif	/* CPU68K_H */
